package com.zzyl.common.utils;

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;

/**
 * 身份证号工具类：支持15/18位身份证解析，计算年龄（无异常抛出，错误时返回0）
 */
public class IdCardAgeUtil {

    // 私有构造：防止工具类被实例化
    private IdCardAgeUtil() {
        throw new AssertionError("工具类禁止实例化");
    }

    // 18位身份证正则（最后一位允许X/x）
    private static final Pattern ID_CARD_18_PATTERN = Pattern.compile("^[1-9]\\d{5}(19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$");
    // 15位身份证正则（年份为2位，默认适配1900-1999/2000-2049）
    private static final Pattern ID_CARD_15_PATTERN = Pattern.compile("^[1-9]\\d{5}\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}$");
    // 日期格式化器（yyyy-MM-dd）
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 核心方法：根据身份证号计算年龄（错误时返回0）
     * @param idCardNo 15位/18位身份证号（可为null或空字符串）
     * @return 正常：实际年龄；异常（格式错/日期无效等）：0
     */
    public static int calculateAge(String idCardNo) {
        // 1. 先判断身份证号是否为空，空则返回0
        if (idCardNo == null || idCardNo.trim().isEmpty()) {
            return 0;
        }
        String trimmedIdCard = idCardNo.trim();

        // 2. 校验身份证格式，格式错返回0
        if (!ID_CARD_18_PATTERN.matcher(trimmedIdCard).matches() 
                && !ID_CARD_15_PATTERN.matcher(trimmedIdCard).matches()) {
            return 0;
        }

        try {
            // 3. 提取出生日期字符串（15位补世纪，18位直接截取）
            String birthDateStr = extractBirthDateStr(trimmedIdCard);
            // 4. 解析出生日期（无效日期会进入catch，返回0）
            LocalDate birthDate = parseBirthDate(birthDateStr);
            // 5. 计算年龄（未到生日自动减1）
            return calculateAgeByBirthDate(birthDate);
        } catch (Exception e) {
            // 任何异常（如字符串截取错、日期解析错）都返回0
            return 0;
        }
    }

    /**
     * 辅助方法：提取出生日期字符串（yyyy-MM-dd格式）
     * @param idCardNo 已校验格式的15位/18位身份证号
     * @return 格式化后的出生日期字符串
     */
    private static String extractBirthDateStr(String idCardNo) {
        String birthDatePart;
        if (idCardNo.length() == 18) {
            // 18位：第7-14位 → yyyyMMdd（例：110101200001011234 → 20000101）
            birthDatePart = idCardNo.substring(6, 14);
        } else {
            // 15位：第7-12位 → yyMMdd，补世纪（yy≥50→19xx，yy<50→20xx）
            String yyPart = idCardNo.substring(6, 8);
            int yy = Integer.parseInt(yyPart);
            String century = yy >= 50 ? "19" : "20";
            birthDatePart = century + idCardNo.substring(6, 12);
        }

        // 转换为 yyyy-MM-dd 格式，方便后续解析
        return birthDatePart.substring(0, 4) + "-" + 
               birthDatePart.substring(4, 6) + "-" + 
               birthDatePart.substring(6, 8);
    }

    /**
     * 辅助方法：解析出生日期字符串为LocalDate
     * @param birthDateStr 格式化后的出生日期（yyyy-MM-dd）
     * @return 出生日期LocalDate对象（异常时会被外层catch捕获）
     */
    private static LocalDate parseBirthDate(String birthDateStr) {
        // LocalDate.parse会校验日期有效性（如2月30日、13月等会抛异常）
        return LocalDate.parse(birthDateStr, DATE_FORMATTER);
    }

    /**
     * 辅助方法：根据出生日期计算真实年龄
     * @param birthDate 出生日期
     * @return 实际年龄（未到生日则减1，最小返回0）
     */
    private static int calculateAgeByBirthDate(LocalDate birthDate) {
        LocalDate today = LocalDate.now();
        Period period = Period.between(birthDate, today);
        int age = period.getYears();

        // 若当前日期还没到今年生日，年龄减1
        if (today.isBefore(birthDate.plusYears(age))) {
            age--;
        }

        // 防止年龄为负数（如出生日期填了未来日期）
        return Math.max(age, 0);
    }
}